import React from "react";
import axios from "axios";
import {saveAs} from 'file-saver'
import type {AxiosResponse, InternalAxiosRequestConfig, AxiosInstance} from 'axios'
import {ExclamationCircleFilled} from "@ant-design/icons";
import {message, notification, modal} from '@/hooks/modules/useMessage.ts';
import {antdSpin} from "antd-spin";
import {errorCode} from "@/utils/errorCode.ts";
import {signString} from "@/utils/authentication.ts";
import {blobValidate} from "@/utils";
import {getCookieToken} from "@/utils/auth";
import {useLogOut} from "@/hooks/modules/useLogOut.ts";


const useRequest: AxiosInstance = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_URL,
    timeout: 10000
})

useRequest.interceptors.request.use((request: InternalAxiosRequestConfig) => {
    request.headers = {
        ...signString({
            needApi: true,
            method: request.method as string,
            path: request.url as string,
            data: request.method == 'get' ? request.params : request.data
        }),
        ...{token: getCookieToken() as string}
    } as any
    // if (getCookieToken()) request.headers['Authorization'] = 'Bearer ' + getCookieToken()
    return request
}, error => {
    Promise.reject(error)
})

useRequest.interceptors.response.use((res: AxiosResponse) => {
        const code = res.data.code || 200;
        const msg = errorCode[code] || res.data.msg || res.data.message || errorCode['default']
        if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
            return res.data
        }
        if (code == 401) {
            message.warning('登录状态已过期，请重新登录。', 3)
            modal.confirm({
                title: '温馨提示 🧡',
                icon: <ExclamationCircleFilled/>,
                content: '登录状态已过期，您可以继续留在该页面，或者重新登录。',
                cancelText: '取消',
                okText: '重新登录',
                onOk: () => {
                    useLogOut()
                }
            });
            return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
        } else if (code === 500) {
            message.error(msg, 3)
            return Promise.reject(new Error(msg))
        } else if (code === 601) {
            message.warning(msg, 3)
            return Promise.reject(new Error(msg))
        } else if (code !== 200 && code !== 0) {
            notification.error({message: msg})
            return Promise.reject('error')
        } else {
            return Promise.resolve(res.data)
        }

    },
    error => {
        let {message: msg} = error;
        if (msg == "Network Error") {
            msg = "后端接口连接异常";
        } else if (msg.includes("timeout")) {
            msg = "系统接口请求超时";
        } else if (msg.includes("Request failed with status code")) {
            msg = "系统接口" + msg.substr(msg.length - 3) + "异常";
        }
        message.error(msg, 5)
        return Promise.reject(error)
    })

class Request {
    post(url: string, data: Record<string, any> = {}): Promise<AxiosResponse<any>> {
        return useRequest.post(url, data)
    }

    get(url: string, params: Record<string, any> = {}): Promise<AxiosResponse<any>> {
        return useRequest.get(url, {params})
    }

    put(url: string, params: Record<string, any> = {}): Promise<AxiosResponse<any>> {
        return useRequest.put(url, params)
    }

    delete(url: string, params: Record<string, any> = {}): Promise<AxiosResponse<any>> {
        return useRequest.delete(url, {params})
    }

    exportFile(url: string, params: Record<string, any>, filename: string, config?: Record<string, any>) {
        let loadingInstance = antdSpin.service({
            fullscreen: true,
            background: 'rgba(0, 0, 0, 0.2)',
            spinProps: {size: "large"}
        });
        return useRequest.post(url, params, {
            responseType: 'blob',
            ...config
        }).then(async (data: any): Promise<void> => {
            const isBlob: boolean = blobValidate(data);
            if (isBlob) {
                const blob: Blob = new Blob([data])
                saveAs(blob, filename)
            } else {
                const resText = await data.text();
                const rspObj = JSON.parse(resText);
                const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
                message.error(errMsg, 3)
            }
            loadingInstance.close();
        }).catch((): void => {
            message.error('导出文件失败！', 3)
            loadingInstance.close();
        })
    }

}

export default new Request()
